<template>
  <div>
    <div style="float: left; color: #42b983; font-size: 16px; font-weight: 500">
      响应式基础
    </div>
    <div>
      <a-button type="primary" @click="increment">{{ count }}</a-button>
    </div>
    <div>
      <a-input v-model:value="count" id="countInput"></a-input>
    </div>
    <div @click="mutateDeeply">{{ obj.nested.count }}</div>
    <a-divider />
    <div>
      <a-button type="primary" @click="debounceCount">我防抖</a-button>
      <a-button @click="jitterCount">我不防抖</a-button>
    </div>
  </div>
</template>
<script>
import { debounce } from "lodash-es";
export default {
  /**
   * debounce 在运行时维护着一个内部状态。如果多个组件实例都共享这同一个预置防抖的函数，那么它们之间将会互相影响
   * 解决方式是创建你多个
   */
  created() {
    // 每个实例都有了自己的预置防抖的处理函数，也可以创建多个防抖函数
    this.debounceCount = debounce(this.antiShaking, 500);
  },
  beforeUnmount() {
    this.debounceCount.cancel();
  },
  data() {
    return {
      count: 0,
      obj: {
        nested: { count: 0 },
      },
      debouncedClick: null,
    };
  },
  methods: {
    jitterCount() {
      this.count++;
    },
    antiShaking() {
      this.count++;
    },
    /**
     * 深层响应
     * ==> 受 ES5 的限制，Vue.js 不能检测到对象属性的添加或删除，如果在实例创建之后添加新的属性到实例上，它不会触发视图更新,需要使用 this.$set()
     */
    mutateDeeply() {
      // 以下都会按照期望工作
      this.obj.nested.count++;
    },
    /**
     * DOM 的更新并不是同步的。相反，Vue 将缓冲它们直到更新周期的 “下个时机”,
     * 以确保无论你进行了多少次状态更改，每个组件都只更新一次
     * ==> 若要等待一个状态改变后的 DOM 更新完成，你可以使用 nextTick() 这个全局 API
     */
    async increment() {
      // 对象已经被修改
      this.count++;
      //   获取 dom 中的数据
      console.log(document.getElementById("countInput").value);
      //   等待一秒，也已不等待，这里是为了演示效果
      await this.sleepUtil(1000);
      //   更新完成之后重新获取doc数据
      this.$nextTick(() => {
        console.log(document.getElementById("countInput").value);
      });
    },
    sleepUtil(millisecond) {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve();
        }, millisecond);
      });
    },
  },
  mounted() {
    // 在其他方法或是生命周期中也可以调用方法
    this.increment();
  },
};
</script>
<style lang="css"></style>
